/*
 * Copyright (C) 2016 Kailash Dabhi (Kingbull Technology)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.omrecorder;

import ohos.media.audio.AudioCapturer;
import ohos.media.audio.AudioCapturerInfo;
import ohos.media.audio.AudioStreamInfo;

/**
 * An {@code AudioSource} is an interface to configure the Audio Source.
 *
 * @author Kailash Dabhi (kailash09dabhi@gmail.com)
 * @date 06-07-2016
 * @skype kailash.09
 */
public interface AudioSource {
    AudioCapturer audioRecorder();

    int channelPositionMask();

    int frequency();

    int minimumBufferSize();

    byte bitsPerSample();

    void isEnableToBePulled(boolean enabledToBePulled);

    boolean isEnableToBePulled();

    /**
     * Application should use this default implementation of {@code AudioSource} to configure the
     * Audio Source.
     */
    class Smart implements AudioSource {
        private final int audioSource;
        private final AudioCapturer audioRecord;
        private final int channelPositionMask;
        private final AudioStreamInfo.EncodingFormat audioEncoding;
        private final int frequency;
        private volatile boolean pull;
        private static final AudioStreamInfo.ChannelMask DEFAULT_CHANNEL_CONFIG = AudioStreamInfo.ChannelMask.CHANNEL_IN_MONO;
        private static final int DEFAULT_LAME_IN_CHANNEL = 1;

        public Smart(int audioSource, AudioStreamInfo.EncodingFormat audioEncoding, int channelPositionMask, int frequency) {
            this.audioSource = audioSource;
            this.audioEncoding = audioEncoding;
            this.channelPositionMask = channelPositionMask;
            this.frequency = frequency;
            AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder()
                    .encodingFormat(audioEncoding) // 16-bit PCM
                    .channelMask(DEFAULT_CHANNEL_CONFIG) // 单声道输入
                    .sampleRate(frequency) // 44.1kHz
                    .build();
            AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder().audioStreamInfo(audioStreamInfo)
                    .build();

            /* Setup audio recorder */
            this.audioRecord = new AudioCapturer(audioCapturerInfo);
        }

        @Override
        public AudioCapturer audioRecorder() {
            return audioRecord;
        }

        @Override
        public int channelPositionMask() {
            return channelPositionMask;
        }

        @Override
        public int frequency() {
            return frequency;
        }

        @Override
        public int minimumBufferSize() {
            return audioRecord.getMinBufferSize(frequency, DEFAULT_LAME_IN_CHANNEL, audioEncoding.getValue());
        }

        @Override
        public byte bitsPerSample() {
            if (audioEncoding.getValue() == AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT.getValue()) {
                return 16;
            } else if (audioEncoding.getValue() == AudioStreamInfo.EncodingFormat.ENCODING_PCM_8BIT.getValue()) {
                return 8;
            } else {
                return 16;
            }
        }

        @Override
        public void isEnableToBePulled(boolean enabledToBePulled) {
            pull = enabledToBePulled;
        }

        @Override
        public boolean isEnableToBePulled() {
            return pull;
        }
    }
}
